﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ClassBuilder.Comment;

namespace ClassBuilder
{
    /// <summary>
    /// 类属性
    /// </summary>
    public class CSPropInfo
    {
    
        public readonly Dictionary<Type, string> TypePairs = new Dictionary<Type, string>()
        {
            {typeof(object),"dynamic" },

            {typeof(bool),"bool" },
            {typeof(bool?),"bool?" },

            {typeof(byte),"byte" },
            {typeof(byte?),"byte?" },

            {typeof(sbyte),"sbyte" },
            {typeof(sbyte?),"sbyte?" },

            {typeof(Int16),"Int16" },
            {typeof(Int16?),"Int16?" },

            {typeof(UInt16),"UInt16" },
            {typeof(UInt16?),"UInt16?" },

            {typeof(int),"int" },
            {typeof(int?),"int?" },

            {typeof(UInt32),"UInt32" },
            {typeof(UInt32?),"UInt32?" },

            {typeof(long),"long" },
            {typeof(long?),"long?" },

            {typeof(UInt64),"UInt64" },
            {typeof(UInt64?),"UInt64?" },

            {typeof(double),"double" },
            {typeof(double?),"double?" },

            {typeof(float),"float" },
            {typeof(float?),"float?" },

            {typeof(decimal),"decimal" },
            {typeof(decimal?),"decimal?" },

            {typeof(char),"char" },
            {typeof(char?),"char?" },

            {typeof(string),"string" },

            {typeof(Guid),"Guid" },
            {typeof(Guid?),"Guid?" },

            {typeof(DateTime),"DateTime" },
            {typeof(DateTime?),"DateTime?" },
        };

        public readonly Dictionary<Type, Func<object, string>> FormatPairs = new Dictionary<Type, Func<object, string>>()
        {
            //{typeof(object),
            //    val =>
            //    {
            //        return val.IsNull()?null:"\""+val.ToString().Trim()+"\"";
            //    }
            //},

            {typeof(bool),
                val =>
                {
                    return val?.ToString().ToLower();
                }
            },
            {typeof(bool?),
                val =>
                {
                     return val.IsNull()?null:val?.ToString()?.ToLower();
                }
            },

            {typeof(byte),
                val =>
                {
                    return val?.ToString();
                }
            },
            {typeof(byte?),
                val =>
                {
                    return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(sbyte),
                val =>
                {
                    return val?.ToString();
                }
            },
            {typeof(sbyte?),
                val =>
                {
                     return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(Int16),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(Int16?),
                val =>
                {
                    return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(UInt16),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(UInt16?),
                val =>
                {
                    return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(int),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(int?),
                val =>
                {
                     return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(UInt32),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(UInt32?),
                val =>
                {
                     return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(long),
                val =>
                {
                     return val.ToString().Trim()+"L";
                }
            },
            {typeof(long?),
                val =>
                {
                    return val.IsNull()?null:val.ToString().Trim()+"L";
                }
            },

            {typeof(UInt64),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(UInt64?),
                val =>
                {
                   return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(double),
                val =>
                {
                    return val.ToString();
                }
            },
            {typeof(double?),
                val =>
                {
                   return val.IsNull()?null:val?.ToString();
                }
            },

            {typeof(float),
                val =>
                {
                    return val.ToString().Trim()+"f";
                }
            },
            {typeof(float?),
                val =>
                {
                    return val.IsNull()?null:val.ToString().Trim()+"f";
                }
            },

            {typeof(decimal),
                val =>
                {
                   return val.ToString().Trim()+"m";
                }
            },
            {typeof(decimal?),
                val =>
                {
                   return val.IsNull()?null:val.ToString().Trim()+"m";
                }
            },

            {typeof(char),
                val =>
                {
                    return "'"+ val.ToString().Trim(' ','\'')+"'";
                }
            },
            {typeof(char?),
                val =>
                {
                    return val.IsNull()?null:"'"+ val.ToString().Trim(' ','\'')+"'";
                }
            },

            {typeof(string),
                val =>
                {
                    return val.IsNull()?null:"\""+val.ToString().Trim(' ','\"')+"\"";
                }
            },

            {typeof(Guid),
                val =>
                {
                    return "Guid.Parse("+val.ToString()+")";
                }
            },
            {typeof(Guid?),
                val =>
                {
                    return val.IsNull()?null:"Guid.Parse("+val.ToString()+")";
                }
            },

            {typeof(DateTime),
                val =>
                {
                    return "DateTime.Parse("+val.ToString()+")";
                }
            },
            {typeof(DateTime?),
                val =>
                {
                    return val.IsNull()?null:"DateTime.Parse("+val.ToString()+")";
                }
            },
        };


        /// <summary>
        /// 属性类型
        /// </summary>
        public Type Type { get; set; } = typeof(object);


        /// <summary>
        /// 属性类型
        /// </summary>
        public string PropTypeName
        {
            get;
            set;
        } = "dynamic";


        /// <summary>
        /// 根据Type 得出 属性类型
        /// </summary>
        /// <param name="type">属性Type类型</param>
        /// <param name="name">属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="comment">属性注释</param>
        public CSPropInfo(Type type, string name, object defaultValue = null, CSComment comment = null)
        {
            this.Type = type;
            if (TypePairs.TryGetValue(this.Type, out string value))
            {
                this.PropTypeName = value;
            }
            this.Name = name;
            this.DefaultValue = defaultValue;
            this.Comment = comment;
            this.IsEnumType = this.Type.IsEnum;
        }

        /// <summary>
        /// 根据默认值 得出 属性类型
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="comment">属性注释</param>
        public CSPropInfo(string name, object defaultValue, CSComment comment = null)
        {
            if (defaultValue.IsNull())
            {
                this.Type = typeof(object);
            }
            else
            {
                this.Type = defaultValue.GetType();
            }
            if (TypePairs.TryGetValue(this.Type, out string value))
            {
                this.PropTypeName = value;
            }
            this.Name = name;
            this.Comment = comment;
            this.DefaultValue = defaultValue;
            this.IsEnumType = this.Type.IsEnum;
        }

        /// <summary>
        /// 自定义 属性类型
        /// </summary>
        /// <param name="propTypeName">属性类型字符串</param>
        /// <param name="name">属性名称</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="comment">属性注释</param>
        /// <param name="isEnumType">是否是枚举类型</param>
        public CSPropInfo(string propTypeName, string name, object defaultValue, CSComment comment = null, bool isEnumType = false)
        {
            this.PropTypeName = propTypeName;
            this.Name = name;
            this.DefaultValue = defaultValue;
            this.Comment = comment;
            this.IsEnumType = isEnumType;
            if (!this.IsEnumType && defaultValue.NotNull())
            {
                this.Type = defaultValue.GetType();

                //传入类型 与 默认值 类型不一致情况
                if (PropTypeName.NotEmpty() 
                    && 
                    !this.Type.Name.Replace("16","").Replace("32", "").Replace("64", "")
                    .Equals(PropTypeName, StringComparison.OrdinalIgnoreCase))
                {
                    this.PropTypeName = "dynamic";
                }
            }
        }


        /// <summary>
        /// 属性名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 属性默认值
        /// </summary>
        public object DefaultValue { get; set; }


        /// <summary>
        /// 是否是枚举类型
        /// </summary>
        public bool IsEnumType { get; set; }

        /// <summary>
        /// 格式化后的默认值
        /// </summary>
        public string FormatValue
        {
            get
            {
                if (DefaultValue.IsNull())
                {
                    return null;
                }
                else
                {
                    if (IsEnumType)
                    {
                        return this.PropTypeName + "." + this.DefaultValue;
                    }
                    else
                    {
                        if (FormatPairs.TryGetValue(this.Type, out Func<object, string> outFunc))
                        {
                            return outFunc.Invoke(this.DefaultValue);
                        }
                    }
                    return DefaultValue.ToString();
                }
            }
        }

        /// <summary>
        /// 属性注释
        /// </summary>
        public CSComment Comment { get; set; }


        public string Value
        {
            get
            {
                return ToString();
            }
        }


        public string[] Lines
        {
            get
            {
                return this.Value?.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
            }
        }

        public override string ToString()
        {
            StringPlus plus = new StringPlus();
            if (Comment != null && Comment.Lines.Length > 0)
            {
                foreach (var line in Comment.Lines)
                {
                    plus.AppendLine(line);
                }
            }
            var strValue = this.DefaultValue.IsNull() ? null : " = " + this.FormatValue + ";";
            plus.Append($"public {PropTypeName} {Name} {{ get; set; }} {strValue}");
            plus.AppendLine();
            return plus.ToString();
        }

       
    }
}
